Modelling results

Are there unconscious visual images in aphantasia? Development of an implicit priming paradigm

Modified

05/09/2024


# Packages ----------------------------------------------------------------

# using a reproducible environment
renv::restore()

# pacman allows to check/install/load packages with a single call
# if (!require("pacman")) install.packages("pacman") # already in renv.lock
library("pacman")

# packages to load (and install if needed) -------------------------------
pacman::p_load(
  here,      # easy file paths
  see,       # theme_modern and okabeito palette
  report,    # reporting various info 
  labelled,  # labelled data
  # ---- packages specific to this project ----
  scales,
  lme4,
  car,
  simr,
  readxl,
  openxlsx,
  statmod,
  qqplotr,
  emmeans,
  latex2exp,
  ggbeeswarm,
  ggpubr,
  patchwork,
  quarto,
  easystats,
  # ---
  tidyverse  # modern R ecosystem
)


# Custom functions shared across scripts ----------------------------------
source(here("scripts/_functions.R"))


# Global cosmetic theme ---------------------------------------------------

theme_set(theme_modern(base_size = 14)) # from see in easystats

# setting my favourite palettes as ggplot2 defaults
options( 
  ggplot2.discrete.colour   = scale_colour_okabeito,
  ggplot2.discrete.fill     = scale_fill_okabeito,
  ggplot2.continuous.colour = scale_colour_viridis_c,
  ggplot2.continuous.fill   = scale_fill_viridis_c
)


# Fixing a seed for reproducibility ---------------------------------------
set.seed(14051998)


# Adding all packages' citations to a .bib --------------------------------
knitr::write_bib(c(.packages()), file = here("bibliography/packages.bib"))

1 Questionnaires analyses

1.1 Group differences

Table

Code
group_effects <- 
  df_questionnaires |>
  pivot_longer(
    cols = c("VVIQ":"SUIS"),
    names_to = "questionnaire",
    values_to = "score"
  ) |> 
  group_by(questionnaire) |> 
  nest() |> 
  rowwise() |> 
  mutate(
    lm = list(lm(score ~ aphantasia, data = data)),
    lm_ranked = list(lm(rank(score) ~ aphantasia, data = data)),
    ranked_means = list(prepare_means(lm_ranked, questionnaire)),
    table = list(generate_model_summary(lm, lm_ranked, questionnaire))
  )

bind_rows(group_effects$table) |> display()
Questionnaire Aphantasics Controls df t p
VVIQ 19.045 ± 0.911 54.242 ± 1.092 149 -21.35 3.49e-47
OSIQ_Object 23.91 ± 0.99 46.581 ± 1.186 149 -13.35 3.08e-27
OSIQ_Spatial 40.955 ± 0.866 45.532 ± 1.038 149 -3.51 5.94e-04
SUIS 17.292 ± 0.749 37.194 ± 0.898 149 -15.63 3.24e-33

Plot

Code
# dodge width for all the geoms
dw <- 1
# axis text size
txt <- 14
# legend text size
txt_legend <- 12

norm_means <- 
  df_q_norm |> 
  group_by(aphantasia) |>
  pivot_longer(
    cols = c(VVIQ:SUIS),
    names_to = "Questionnaire",
    values_to = "score"
  ) |> 
  group_by(Questionnaire) |> 
  nest() |> 
  rowwise() |> 
  mutate(
    lm = list(lm(score ~ aphantasia, data = data)),
    means = list(estimate_means(lm, by = "aphantasia"))
  ) |> 
  unnest(means) |> 
  select(!c(data, lm)) |> 
  ungroup() |> 
  mutate(
    Questionnaire = fct_relevel(
      Questionnaire,
      c("VVIQ", "SUIS", "OSIQ_Object", "OSIQ_Spatial")
    ))
Code
df_q_norm |> 
  
  # Long format first -----------------------------------------------------
  pivot_longer(
    cols = c(VVIQ:SUIS),
    names_to = "Questionnaire",
    values_to = "Score"
  ) |>
  mutate(
    Questionnaire = fct_relevel(
      Questionnaire, 
      c("VVIQ", "SUIS", "OSIQ_Object", "OSIQ_Spatial")
    )) |> 
  
  # Plotting --------------------------------------------------------------
  ggplot(aes(
    x = Questionnaire, 
    y = Score, 
    fill = aphantasia, 
    color = aphantasia
    )) +
  
  # accentuation of the median line at 0.5
  geom_hline(
    yintercept = .5,
    linetype = 1,
    color = "grey30",
    alpha = .2
  ) +
  
  # Scores ---------------------------------------------------------------
  # violin shapes for the distributions and quantiles
  geom_violin(
    position = position_dodge(dw),
    alpha = .1,
    draw_quantiles = c(.25, .5, .75)
  ) +
  # points for means and lines for CIs
  geom_pointrange(
    data = norm_means,
    aes(
      x = Questionnaire,
      y = Mean,
      ymin = CI_low,
      ymax = CI_high,
      color = aphantasia
    ),
    size = .75,
    linewidth = 1,
    position = position_dodge(dw)
  ) +
  
  # Stars and lines --------------------------------------------------------
  # stars for significance
  annotate(
    geom  = "text", label = "***", color = "black",
    x = 1, y = .95, size  = 10 
    ) +
  # dotted line that separates the different questionnaires
  geom_vline(
    aes(xintercept = stage(Questionnaire, after_scale = 1.5)),
    linetype = 3
  ) +
  # stars 
  annotate(
    geom  = "text", label = "***", color = "black",
    x = 2, y = .95, size  = 10 
    ) +
  # dotted line
  geom_vline(
    aes(xintercept = stage(Questionnaire, after_scale = 2.5)),
    linetype = 3
  ) +
  # stars
  annotate(
    geom  = "text", label = "***", color = "black",
    x = 3, y = .95, size  = 10 
    ) +
  # dotted line
  geom_vline(
    aes(xintercept = stage(Questionnaire, after_scale = 3.5)),
    linetype = 3
  ) +
  # stars
  annotate(
    geom  = "text", label = "***", color = "black",
    x = 4, y = .95, size  = 10 
    ) +
  
  # Aesthetics -------------------------------------------------------------
  scale_color_okabeito(name = "Group:  ", labels = c(" Control   ", " Aphantasic")) +
  scale_fill_okabeito(name = "Group:  ", labels  = c(" Control   ", " Aphantasic")) +
  scale_x_discrete(
    name = "",
    labels = c("VVIQ", "SUIS", "OSIQ-Object", "OSIQ-Spatial")
  ) +
  scale_y_continuous(
    name = "Standardized score",
    breaks = breaks_pretty(8)
  ) +
  theme(
    panel.grid.major.x = element_blank(),
    panel.grid.major.y = element_line(),
    axis.text.x  = element_text(size = txt),
    axis.title.y = element_text(size = txt),
    legend.title = element_text(size = txt_legend),
    legend.text  = element_text(size = txt_legend),
    legend.position = "top"
    )

# ggsave(here("figures/questionnaires.png"), dpi = 600)
Figure 1.1

1.2 Congruence effects

Correlations

Code
corr_whole <- 
  df_questionnaires |> 
    select(4:10) |>
    correlation(method = "spearman", p_adjust = "fdr") 

corr_aph <-
  df_questionnaires |>
    select(4:10) |>
    filter(aphantasia == "yes") |>
    correlation(method = "spearman", p_adjust = "fdr") 

corr_control <-
  df_questionnaires |>
    select(4:10) |>
    filter(aphantasia == "no")  |>
    correlation(method = "spearman", p_adjust = "fdr") 

# corr_whole
# corr_aph
# corr_control
Code
corr_whole |> summary() |> plot() + 
  labs(title = "Correlation matrix, whole group (Spearman FDR corrected)")

# ggsave(here("figures/corr-mat-whole.png"), dpi = 600)

corr_aph |> summary() |> plot() +
  labs(title = "Correlation matrix, aphantasia group only (Spearman FDR corrected)")

# ggsave(here("figures/corr-mat-aph.png"), dpi = 600)

corr_control |> summary() |> plot() +
  labs(title = "Correlation matrix, control group only (Spearman FDR corrected)")

# ggsave(here("figures/corr-mat-control.png"), dpi = 600)

Plots

Code
note_size = 6

# Ranked versions
p_corr_vviq <-
  df_q_ranked |> 
  plot_correlations("VVIQ", "Implicit effect") +
  labs(x = "VVIQ (ranked)", y = "Implicit effect") +
  annotate(
    geom  = "text", 
    label = TeX(r"($\rho = 0.21, \textit{p} = 0.02$)"), 
    color = "black",
    x = 89, y = .25, 
    size  = note_size 
    )

p_corr_osiq <-
  df_q_ranked |> 
  plot_correlations("OSIQ_Object", "Implicit effect") +
  labs(x = "OSIQ-Object (ranked)", y = "Implicit effect") +
  annotate(
    geom  = "text", 
    label = TeX(r"($\rho = 0.26, \textit{p} = 0.003$)"), 
    color = "black",
    x = 80, y = .25, 
    size  = note_size 
    )

p_corr_suis <-
  df_q_ranked |> 
  plot_correlations("SUIS", "Implicit effect") +
  labs(x = "SUIS (ranked)", y = "Implicit effect") +
  annotate(
    geom  = "text", 
    label = TeX(r"($\rho = 0.27, \textit{p} = 0.002$)"), 
    color = "black",
    x = 81, y = .25, 
    size  = note_size 
    )
Code
layout <- "
AAAABBBB
##CCCC##
"

# ((p_corr_vviq + p_corr_osiq) / p_corr_suis) +
(p_corr_vviq + p_corr_osiq + p_corr_suis) +
  plot_layout(design = layout, guides = "collect") &
  theme(
    legend.position = "top", 
    legend.text = element_text(size = 20),
    legend.title = element_blank(),
    axis.title = element_text(size = 16)
    )

Code
# ggsave(here("figures/corr-plots.png"), dpi = 600)

2 Accuracy analyses

We will quickly check for accuracy differences between groups with a logistic regression model.

Code
fit_acc_im <- 
  glmer(
    formula = correct_implicit ~ (aphantasia + congruence + color)^3 + (1 | subjectid),
    data = df_i_acc,
    family = binomial(link = "logit"),
  control = glmerControl(optimizer = "bobyqa")
  )

fit_acc_ex <- 
  glmer(
    formula = correct_explicit ~ (aphantasia + congruence + color)^3 + (1 | subjectid),
    data = df_e_acc,
    family = binomial(link = "logit"),
    control = glmerControl(optimizer = "bobyqa")
  )
Code
model_performance(fit_acc_im) |> display()
Code
model_parameters(fit_acc_im) |> display()
Table S2.1: Performance and estimates of the logistic GLMM fitted on accuracy in the implicit task.
AIC AICc BIC R2 (cond.) R2 (marg.) ICC RMSE Sigma Log_loss Score_log
2614.99 2615.01 2679.02 0.17 9.48e-03 0.16 0.18 1.00 0.13 -Inf
# Fixed Effects
Parameter Log-Odds SE 95% CI z p
(Intercept) 3.64 0.10 (3.43, 3.84) 34.70 < .001
aphantasia1 0.19 0.19 (-0.18, 0.56) 1.01 0.312
congruence1 0.05 0.12 (-0.18, 0.29) 0.44 0.659
color1 0.32 0.12 (0.08, 0.55) 2.63 0.009
aphantasia1 × congruence1 0.15 0.24 (-0.32, 0.63) 0.64 0.519
aphantasia1 × color1 -0.18 0.24 (-0.65, 0.29) -0.74 0.462
congruence1 × color1 8.71e-03 0.24 (-0.46, 0.48) 0.04 0.971
aphantasia1 × congruence1 × color1 0.34 0.48 (-0.60, 1.29) 0.72 0.473
# Random Effects
Parameter Coefficient
SD (Intercept: subjectid) 0.79
Code
estimate_means(fit_acc_im, by = "aphantasia", transform = "response") |> display()
Code
estimate_contrasts(fit_acc_im, contrast = "aphantasia", transform = "response", p_adjust = "none") |> display()
Table S2.2: Estimated probability of a correct answer and log-odds contrasts between groups for the accuracy in the implicit task.
Estimated Marginal Means
aphantasia Probability SE 95% CI
Control 0.97 4.07e-03 (0.96, 0.98)
Aphantasia 0.98 3.02e-03 (0.97, 0.98)

Marginal means estimated at aphantasia

Marginal Contrasts Analysis
Level1 Level2 Odds ratio 95% CI SE df z p
Control Aphantasia 0.83 (0.57, 1.20) 0.16 Inf -1.01 0.312

Marginal contrasts estimated at aphantasia p-values are uncorrected.

Code
model_performance(fit_acc_ex) |> display()
Code
model_parameters(fit_acc_ex) |> display()
Table S2.3: Performance and estimates of the logistic GLMM fitted on accuracy in the explicit task.
AIC AICc BIC R2 (cond.) R2 (marg.) ICC RMSE Sigma Log_loss Score_log
2020.26 2020.28 2084.03 0.18 0.03 0.16 0.15 1.00 0.11 -Inf
# Fixed Effects
Parameter Log-Odds SE 95% CI z p
(Intercept) 3.98 0.12 (3.74, 4.21) 33.19 < .001
aphantasia1 0.21 0.21 (-0.19, 0.62) 1.03 0.304
congruence1 0.12 0.15 (-0.16, 0.41) 0.84 0.401
color1 0.65 0.15 (0.37, 0.94) 4.49 < .001
aphantasia1 × congruence1 -8.30e-03 0.29 (-0.58, 0.56) -0.03 0.977
aphantasia1 × color1 -0.24 0.29 (-0.81, 0.33) -0.83 0.407
congruence1 × color1 0.32 0.29 (-0.25, 0.89) 1.11 0.265
aphantasia1 × congruence1 × color1 -0.31 0.58 (-1.45, 0.83) -0.53 0.595
# Random Effects
Parameter Coefficient
SD (Intercept: subjectid) 0.78
Code
estimate_means(fit_acc_ex, by = "aphantasia", transform = "response") |> display()
Code
estimate_contrasts(fit_acc_ex, contrast = "aphantasia", transform = "response", p_adjust = "none") |> display()
Table S2.4: Estimated probability of a correct answer and log-odds contrasts between groups for the accuracy in the explicit task.
Estimated Marginal Means
aphantasia Probability SE 95% CI
Control 0.98 3.37e-03 (0.97, 0.99)
Aphantasia 0.98 2.40e-03 (0.98, 0.99)

Marginal means estimated at aphantasia

Marginal Contrasts Analysis
Level1 Level2 Odds ratio 95% CI SE df z p
Control Aphantasia 0.81 (0.54, 1.21) 0.17 Inf -1.03 0.304

Marginal contrasts estimated at aphantasia p-values are uncorrected.

3 Response Times analyses

3.1 Rationale

To account for the non-normal, positively skewed distributions of the RTs, we fitted Generalized Linear Mixed Models (GLMMs) with inverse Gaussian distributions. The models were implemented in the lme4 R package and integrated in tidymodels workflows using the package multilevelmod. Models with Gamma and Gaussian distributions were also fitted and compared with the AIC and BIC to ensure that we chose the best distribution available.

The models included the Group (aphantasic, control), Congruence condition (congruent or incongruent) and Color condition (color or uncolored) along with all their two and three way interactions as fixed categorical predictors, while participants have been included as grouping factors (i.e. “random effects”). The random effect structure was chosen by fitting and comparing models with every possible combination of distribution and structure (intercept by participant, congruence or color, slope by participant on congruence and/or color) aiming for the best balance between goodness of fit and parsimony. Complex random-effects structures including various slopes on the factors failed to converge to stable and reliable estimates, hence the optimal models chosen included a single by-participant random intercept.

3.2 Model fitting

The formula of the model fitted is \(RT \sim (aphantasia + congruence + color)^3 + (1|subjectid)\).

model_formula <- rt ~ (aphantasia + congruence + color)^3 + (1|subjectid)

fit_implicit <- 
  glmer(
    formula = model_formula,
    data = df_i_rt,
    family = inverse.gaussian(link = "identity"),
    control = glmerControl(optimizer = "bobyqa")
  )

fit_explicit <- 
  glmer(
    formula = model_formula,
    data = df_e_rt,
    family = inverse.gaussian(link = "identity"),
    control = glmerControl(optimizer = "bobyqa")
  )

3.3 Model diagnostics

The quality checks of the models are displayed in Figure S3.1 and Figure S3.2 .

Code
# characteristics to check
model_checks <- c("pp_check","homogeneity", "vif", "outliers", "qq", "reqq")

check_model(
  fit_implicit, 
  checks = model_checks, 
  detrend = FALSE, 
  residual_type = "normal"
  ) |> 
  plot()

# ggsave(here("figures/checks-implicit.png"), dpi = 600)
Figure S3.1: Model assumption checks for the Generalized Linear Mixed Model fit on the RTs in the implicit task.
Code
check_model(
  fit_explicit, 
  checks = model_checks, 
  detrend = FALSE, 
  residual_type = "normal"
  ) |> 
  plot()

# ggsave(here("figures/checks-explicit.png"), dpi = 600)
Figure S3.2: Model assumption checks for the Generalized Linear Mixed Model fit on the RTs in the explicit task.

3.4 Model summaries

Table S3.1: Performance and estimates of the GLMM fitted on the implicit task data.
AIC AICc BIC R2 (cond.) R2 (marg.) ICC RMSE Sigma
-4619.06 -4619.03 -4548.26 0.01 3.47e-04 0.01 0.26 0.48
# Fixed Effects
Parameter Coefficient SE 95% CI t(8767) p
(Intercept) 0.67 0.01 (0.64, 0.69) 53.99 < .001
aphantasia1 0.02 0.02 (-0.03, 0.07) 0.77 0.442
congruence1 -0.01 4.03e-03 (-0.02, -5.69e-03) -3.37 < .001
color1 -2.57e-03 4.02e-03 (-0.01, 5.32e-03) -0.64 0.523
aphantasia1 × congruence1 0.02 8.05e-03 (7.70e-03, 0.04) 2.92 0.004
aphantasia1 × color1 -7.96e-04 8.04e-03 (-0.02, 0.01) -0.10 0.921
congruence1 × color1 0.01 8.03e-03 (-5.65e-03, 0.03) 1.26 0.209
aphantasia1 × congruence1 × color1 0.02 0.02 (-0.01, 0.05) 1.20 0.229
# Random Effects
Parameter Coefficient
SD (Intercept: subjectid) 0.08
SD (Residual) 0.48
Table S3.2: Performance and estimates of the GLMM fitted on the explicit task data.
AIC AICc BIC R2 (cond.) R2 (marg.) ICC RMSE Sigma
-2673.61 -2673.58 -2603.01 0.03 7.96e-04 0.03 0.28 0.41
# Fixed Effects
Parameter Coefficient SE 95% CI t(8593) p
(Intercept) 0.79 0.02 (0.75, 0.83) 37.14 < .001
aphantasia1 0.01 0.04 (-0.07, 0.09) 0.25 0.799
congruence1 -0.02 4.21e-03 (-0.03, -9.82e-03) -4.29 < .001
color1 -0.03 4.20e-03 (-0.04, -0.02) -6.93 < .001
aphantasia1 × congruence1 0.03 8.42e-03 (0.01, 0.04) 3.19 0.001
aphantasia1 × color1 7.19e-03 8.39e-03 (-9.26e-03, 0.02) 0.86 0.392
congruence1 × color1 2.74e-03 8.39e-03 (-0.01, 0.02) 0.33 0.744
aphantasia1 × congruence1 × color1 0.01 0.02 (-0.02, 0.05) 0.84 0.402
# Random Effects
Parameter Coefficient
SD (Intercept: subjectid) 0.12
SD (Residual) 0.41

3.5 Estimated means and contrasts

Table S3.3: Estimated means for each group in each congruence condition and contrasts between groups and conditions in the implicit task.
Group Condition Median (ms) SE df asymp.LCL asymp.UCL
Control Incongruent 669.71 19.36 Inf 631.77 707.65
Aphantasia Incongruent 676.89 15.84 Inf 645.84 707.93
Control Congruent 644.38 19.31 Inf 606.53 682.22
Aphantasia Congruent 675.05 15.83 Inf 644.02 706.08
Marginal Contrasts Analysis
Level1 Level2 Difference 95% CI SE df z p
Aphantasia Incongruent Aphantasia Congruent 1.84e-03 (-0.01, 0.01) 5.23e-03 Inf 0.35 0.725
Aphantasia Incongruent Control Congruent 0.03 (-0.02, 0.08) 0.02 Inf 1.30 0.193
Control Congruent Aphantasia Congruent -0.03 (-0.08, 0.02) 0.02 Inf -1.23 0.219
Control Incongruent Aphantasia Congruent -5.34e-03 (-0.05, 0.04) 0.02 Inf -0.21 0.831
Control Incongruent Aphantasia Incongruent -7.18e-03 (-0.06, 0.04) 0.02 Inf -0.29 0.774
Control Incongruent Control Congruent 0.03 ( 0.01, 0.04) 6.13e-03 Inf 4.13 < .001

Marginal contrasts estimated at aphantasia, congruence p-values are uncorrected.

Table S3.4: Estimated means for each group in each congruence condition and contrasts between groups and conditions in the explicit task.
Group Condition Median (ms) SE df asymp.LCL asymp.UCL
Control Incongruent 801.78 33.22 Inf 736.68 866.88
Aphantasia Incongruent 799.21 27.05 Inf 746.18 852.23
Control Congruent 770.29 33.17 Inf 705.28 835.30
Aphantasia Congruent 794.57 27.04 Inf 741.56 847.57
Marginal Contrasts Analysis
Level1 Level2 Difference 95% CI SE df z p
Aphantasia Incongruent Aphantasia Congruent 4.64e-03 (-0.01, 0.02) 5.45e-03 Inf 0.85 0.394
Aphantasia Incongruent Control Congruent 0.03 (-0.05, 0.11) 0.04 Inf 0.68 0.499
Control Congruent Aphantasia Congruent -0.02 (-0.11, 0.06) 0.04 Inf -0.57 0.570
Control Incongruent Aphantasia Congruent 7.21e-03 (-0.08, 0.09) 0.04 Inf 0.17 0.866
Control Incongruent Aphantasia Incongruent 2.57e-03 (-0.08, 0.09) 0.04 Inf 0.06 0.952
Control Incongruent Control Congruent 0.03 ( 0.02, 0.04) 6.42e-03 Inf 4.91 < .001

Marginal contrasts estimated at aphantasia, congruence p-values are uncorrected.

3.6 Visualisations

The figures below are also displayed in the main article. [See the HTML version for the code and details.] {.content-hidden when-format=“html”}

Code
subj_means_im <-
  df_i_rt |> 
  group_by(subjectid, aphantasia, congruence) |>
  reframe(rt = mean(rt)*1000)

(
  plot_models_full(subj_means_im, emmeans_im, y_min = 400, y_max = 1110, size = 4) +
  plot_models_zoomed(subj_means_im, emmeans_im, size = 4) &
  theme(
    legend.position = "top",
    legend.title = element_blank(),
    legend.text = element_text(size = 20),
    legend.margin = margin(0, 150, 25, 0),
    axis.title.y = element_text(size = 20),
    axis.text.x = element_text(size = 18)
  )
) +
  plot_layout(
    guides = "collect",
    widths = c(1, 1.2)
  )

# ggsave(here("figures/model-implicit.png"), dpi = 600)
Figure 3.1: Subject means and model-estimated means per group and condition in the implicit task.
Code
subj_means_ex <-
  df_e_rt |> 
  group_by(subjectid, aphantasia, congruence) |>
  reframe(rt = mean(rt)*1000)

(
  plot_models_full(subj_means_ex, emmeans_ex, y_min = 350, y_max = 1450, size = 4) +
  plot_models_zoomed(subj_means_ex, emmeans_ex, size = 4) &
  theme(
    legend.position = "top",
    legend.title = element_blank(),
    legend.text = element_text(size = 20),
    legend.margin = margin(0, 150, 25, 0),
    axis.title.y = element_text(size = 20),
    axis.text.x = element_text(size = 18)
  )
) +
  plot_layout(
    guides = "collect",
    widths = c(1, 1.2)
  )

# ggsave(here("figures/model-explicit.png"), dpi = 600)
Figure 3.2: Subject means and model-estimated means per group and condition in the explicit task.

4 Correlational analyses

     

═════════════════════════════════════════════════════════════════════════
Analyses were conducted using the R Statistical language (version 4.4.1; R Core
Team, 2024) on Windows 11 x64 (build 22631)
Packages used:
  - quarto (version 1.4.4; Allaire J, Dervieux C, 2024)
  - qqplotr (version 0.0.6; Almeida A et al., 2018)
  - lme4 (version 1.1.35.5; Bates D et al., 2015)
  - Matrix (version 1.7.0; Bates D et al., 2024)
  - effectsize (version 0.8.9; Ben-Shachar MS et al., 2020)
  - ggbeeswarm (version 0.7.2; Clarke E et al., 2023)
  - car (version 3.1.2; Fox J, Weisberg S, 2019)
  - carData (version 3.0.5; Fox J et al., 2022)
  - statmod (version 1.5.0; Giner G, Smyth GK, 2016)
  - simr (version 1.0.7; Green P, MacLeod CJ, 2016)
  - lubridate (version 1.9.3; Grolemund G, Wickham H, 2011)
  - ggpubr (version 0.6.0; Kassambara A, 2023)
  - labelled (version 2.13.0; Larmarange J, 2024)
  - emmeans (version 1.10.3; Lenth R, 2024)
  - parameters (version 0.22.0; Lüdecke D et al., 2020)
  - performance (version 0.12.0; Lüdecke D et al., 2021)
  - easystats (version 0.7.2; Lüdecke D et al., 2022)
  - see (version 0.8.4; Lüdecke D et al., 2021)
  - insight (version 0.20.1; Lüdecke D et al., 2019)
  - bayestestR (version 0.13.2; Makowski D et al., 2019)
  - modelbased (version 0.8.8; Makowski D et al., 2020)
  - report (version 0.5.8; Makowski D et al., 2023)
  - correlation (version 0.8.5; Makowski D et al., 2022)
  - latex2exp (version 0.9.6; Meschiari S, 2022)
  - here (version 1.0.1; Müller K, 2020)
  - tibble (version 3.2.1; Müller K, Wickham H, 2023)
  - datawizard (version 0.11.0; Patil I et al., 2022)
  - patchwork (version 1.2.0; Pedersen T, 2024)
  - R (version 4.4.1; R Core Team, 2024)
  - pacman (version 0.5.1; Rinker TW, Kurkiewicz D, 2018)
  - openxlsx (version 4.2.5.2; Schauberger P, Walker A, 2023)
  - ggplot2 (version 3.5.1; Wickham H, 2016)
  - forcats (version 1.0.0; Wickham H, 2023)
  - stringr (version 1.5.1; Wickham H, 2023)
  - tidyverse (version 2.0.0; Wickham H et al., 2019)
  - readxl (version 1.4.3; Wickham H, Bryan J, 2023)
  - dplyr (version 1.1.4; Wickham H et al., 2023)
  - purrr (version 1.0.2; Wickham H, Henry L, 2023)
  - readr (version 2.1.5; Wickham H et al., 2024)
  - scales (version 1.3.0; Wickham H et al., 2023)
  - tidyr (version 1.3.1; Wickham H et al., 2024)
═════════════════════════════════════════════════════════════════════════